package com.yuanfeng.payment.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.jfinal.kit.StrKit;
import com.jfinal.weixin.sdk.api.PaymentApi;
import com.jfinal.weixin.sdk.kit.PaymentKit;
import com.jfinal.weixin.sdk.utils.JsonUtils;
import com.yuanfeng.commoms.config.WXConfigUtil;
import com.yuanfeng.commoms.config.WXPayConfig;
import com.yuanfeng.commoms.config.WXPayConfigShop;
import com.yuanfeng.commoms.config.YFConfig;
import com.yuanfeng.commoms.exception.BizCodeEnume;
import com.yuanfeng.commoms.util.ParseTokenUtils;
import com.yuanfeng.commoms.util.PayToolUtil;
import com.yuanfeng.commoms.util.RedisUtil;
import com.yuanfeng.commoms.util.ResponseResult;
import com.yuanfeng.commoms.vo.user.UserInfoVO;
import com.yuanfeng.payment.dto.GoodsDTO;
import com.yuanfeng.payment.feign.UsermsServiceClient;
import com.yuanfeng.payment.mapper.PayConfigMapper;
import com.yuanfeng.payment.mapper.PayConsumeRecordMapper;
import com.yuanfeng.payment.mapper.PayConsumeTradeBackMapper;
import com.yuanfeng.payment.mapper.PayConsumeTradeMapper;
import com.yuanfeng.payment.service.PayConsumeTradeService;
import com.yuanfeng.payment.service.PayStrategyHandleService;
import com.yuanfeng.payment.vo.CallBackVO;
import com.yuanfeng.payment.vo.RecordVO;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author Stranger
 * @date 2023/4/13 15:16
 */
@Service
public class WXAppletPayServicesImpl implements PayStrategyHandleService {


    private static PayConfigMapper payConfigMapper;


    private static PayConsumeTradeMapper payConsumeTradeMapper;


    private static PayConsumeTradeBackMapper payConsumeTradeBackMapper;


    private static PayConsumeRecordMapper payConsumeRecordMapper;


    private static UsermsServiceClient usermsServiceClient;

    private static PayConsumeTradeService payConsumeTradeService;

    private static  RestTemplate restTemplate;

    // 注入的时候，给类的 service 注入
    @Autowired
    public void setUsermsServiceClient(UsermsServiceClient usermsServiceClient, PayConsumeTradeService payConsumeTradeService, RestTemplate restTemplate) {

        WXAppletPayServicesImpl.usermsServiceClient = usermsServiceClient;
        WXAppletPayServicesImpl.payConsumeTradeService=payConsumeTradeService;
        WXAppletPayServicesImpl.restTemplate=restTemplate;
    }

    // 注入的时候，给类的 service 注入
    @Autowired
    public void setMapper(PayConfigMapper payConfigMapper, PayConsumeTradeMapper payConsumeTradeMapper,
                          PayConsumeTradeBackMapper payConsumeTradeBackMapper, PayConsumeRecordMapper payConsumeRecordMapper) {
        WXAppletPayServicesImpl.payConfigMapper = payConfigMapper;
        WXAppletPayServicesImpl.payConsumeTradeMapper = payConsumeTradeMapper;
        WXAppletPayServicesImpl.payConsumeTradeBackMapper = payConsumeTradeBackMapper;
        WXAppletPayServicesImpl.payConsumeRecordMapper = payConsumeRecordMapper;
    }

    final static Logger log = LoggerFactory.getLogger(WXAppletPayServicesImpl.class);

    /**
     * 初始化 阿里云支付参数
     */
    public void initWXPayConfig() {
        //微信 pc  h5
        String paymentMode = "00";
        Map<String, Object> outMap = payConfigMapper.selectPayConfig(paymentMode);
        WXPayConfig.API_KEY = outMap.get("appAPIKey").toString();
        WXPayConfig.APP_SECRET = outMap.get("appSecret").toString();
        WXPayConfig.MCH_ID = outMap.get("appMCHId").toString();
        WXPayConfig.APP_ID = outMap.get("appID").toString();
        WXPayConfig.NOTIFY_URL = outMap.get("notifyUrl").toString();
        WXPayConfig.REDIRECT_URL = outMap.get("redirectUrl").toString();
        WXPayConfig.weChatWapPath = outMap.get("weChatPcPath").toString();

        //微信app
        WXConfigUtil.KEY = outMap.get("appAPIKey").toString();
        WXConfigUtil.APP_SECRET = outMap.get("appSecret").toString();
        WXConfigUtil.MCH_ID = outMap.get("appMCHId").toString();
        WXConfigUtil.APP_ID = outMap.get("appID").toString();
        WXConfigUtil.NOTIFY_URL_APP = outMap.get("notifyUrl").toString();
        //微信小程序
        String paymentMode2 = "02";
        Map<String, Object> outMap2 = payConfigMapper.selectPayConfig(paymentMode2);
        WXPayConfig.Applet_APP_ID = outMap2.get("appID").toString();
        WXPayConfig.Applet_APP_SECRET = outMap2.get("appSecret").toString();



    }

    @Override
    public ResponseResult userPayEntrance(Map<Object, Object> map, HttpServletRequest request, HttpServletResponse response) {
        //查询支付配置信息
        this.initWXPayConfig();
        String outTradeNo = (String) map.get("orderId");
        String code = (String) map.get("code");
        String openId = (String) map.get("openId");
        String token = (String) map.get("token");
        Map<String,String> param = new HashMap<>();
        param.put("code",code);
        param.put("token",token);
        if(StringUtils.isEmpty(openId)){
            //小程序账号密码登陆获取openid
            try {
                String strUrl = String.format(WXPayConfig.getCODE_SESSION(), code);
                String resultStr = restTemplate.getForObject(strUrl, String.class);
                resultStr = new String(resultStr.getBytes("ISO-8859-1"), "UTF-8");
                JSONObject result1 = JSONObject.parseObject(resultStr);
                openId = result1.getString("openid");
            } catch (UnsupportedEncodingException e) {
                throw new RuntimeException(e);
            }
        }
        BigDecimal totalPrice = new BigDecimal(0);
        //积分商品 0  是  1 否
        Integer integralGoods = 1;
        Integer amountAotalIntegral = null;
        String goodsName = "订单编号" + outTradeNo;
        try{
            UserInfoVO ui = ParseTokenUtils.getUserInfoByToken(token);
            String userId = ui.getUserId();
            if (openId == null) {
                openId = ui.getBindOpenid();
            }
            List<CallBackVO> callBackParaList = payConsumeTradeService.treasureOrder(token, outTradeNo);

            // 查询商品名与商品价格
            if (PayToolUtil.isInteger(outTradeNo)) {
                GoodsDTO queryGoodsPara = payConsumeTradeMapper.queryGoodsPriceAndName(outTradeNo);
                // 总价
                totalPrice = queryGoodsPara.getTradePaymentAmount();

                RedisUtil.set(YFConfig.YF_TREASUREPARA + outTradeNo, JSON.toJSONString(callBackParaList),
                        21600);

                //GoodsDTO queryGoodsPara2 = payConsumeTradeBackMapper.queryGoodsPriceAndName(outTradeNo, userId);
                //获取积分商品订单的积分
                Integer totalIntegral = queryGoodsPara.getTotalIntegral();
                //积分商品 0  是  1 否
                integralGoods = queryGoodsPara.getIntegralGoods();
                amountAotalIntegral = totalIntegral;
            }else{
                List<RecordVO> rp = payConsumeRecordMapper.queryRecordParaList(outTradeNo);
                for (RecordVO recordVO : rp) {
                    BigDecimal price = recordVO.getRecordMoney();
                    totalPrice = totalPrice.add(price);
                }
                RedisUtil.set(YFConfig.YF_TREASUREPARA + outTradeNo, JSON.toJSONString(callBackParaList),
                        21600);
                // 获取积分商品的积分
                String totalIntegral = RedisUtil
                        .get(YFConfig.YF_USERINTEGRALYPAID + "--" + token + "--" + ui.getUserId());
                if (null != totalIntegral) {
                    //amountAotalIntegral 不为null 证明是积分订单
                    amountAotalIntegral = Integer.valueOf(totalIntegral);
                    //积分商品 0  是  1 否
                    integralGoods = 0;
                }
            }
            if (null != integralGoods && integralGoods == 0) {
                //获取用户积分
                Integer userIntegral = usermsServiceClient.getMemberIntegralByUserId(userId);
                if (null != userIntegral && amountAotalIntegral > userIntegral) {
                    //账户积分不足
                    return ResponseResult.fail(BizCodeEnume.PAY_INTEGRAL_ERROR);
                }
            }
            // 处理自营店铺
            if (!StringUtils.isEmpty(RedisUtil.get(YFConfig.YF_ORDER_USER_TOKEN + outTradeNo))) {
                RedisUtil.remove(YFConfig.YF_ORDER_USER_TOKEN + outTradeNo);
            }
            RedisUtil.set(YFConfig.YF_ORDER_USER_TOKEN + outTradeNo, token, 86400);
            String payAmount = String.valueOf(totalPrice);
            String price = PayToolUtil.getMoney(payAmount);
            Map<String, String> params = new HashMap<String, String>();
            WXPayConfigShop configShop = null;
            if (map.get("shopId") != null && map.get("shopId") != ""){
                //品牌店铺
                configShop = payConfigMapper.selectYfPayConfigShop((Integer) map.get("shopId"));
                params.put("appid", configShop.getApplet_APP_ID());
                params.put("mch_id", configShop.getMCH_ID());
                params.put("nonce_str", PayToolUtil.create_nonce_str());
                params.put("body", goodsName);
                params.put("out_trade_no", outTradeNo);
                params.put("total_fee", price);

                params.put("spbill_create_ip", PayToolUtil.getIpAddr(request));
                params.put("notify_url", configShop.NOTIFY_URL);
                params.put("trade_type", "JSAPI");
                params.put("openid", openId);

                String sign = PaymentKit.createSign(params, configShop.getAPI_KEY());
                params.put("sign", sign);

            }else{
                params.put("appid", WXPayConfig.Applet_APP_ID);
                params.put("mch_id", WXPayConfig.MCH_ID);
                params.put("nonce_str", PayToolUtil.create_nonce_str());
                params.put("body", goodsName);
                params.put("out_trade_no", outTradeNo);
                params.put("total_fee", price);

                params.put("spbill_create_ip", PayToolUtil.getIpAddr(request));
                params.put("notify_url", WXPayConfig.NOTIFY_URL);
                params.put("trade_type", "JSAPI");
                params.put("openid", openId);

                String sign = PaymentKit.createSign(params, WXPayConfig.API_KEY);
                params.put("sign", sign);
            }

            String xmlResult = PaymentApi.pushOrder(params);
            Map<String, String> result = PaymentKit.xmlToMap(xmlResult);

            String return_code = result.get("return_code");
            String return_msg = result.get("return_msg");
            if (StrKit.isBlank(return_code) || !"SUCCESS".equals(return_code)) {
                return ResponseResult.fail(return_msg);
            }
            String result_code = result.get("result_code");
            if (StrKit.isBlank(result_code) || !"SUCCESS".equals(result_code)) {
                return ResponseResult.fail(return_msg);
            }

            String prepay_id = result.get("prepay_id");

            Map<String, String> packageParams = new HashMap<String, String>();
            if (configShop != null){
                packageParams.put("appId", configShop.getApplet_APP_ID());
                packageParams.put("timeStamp", System.currentTimeMillis() / 1000 + "");
                packageParams.put("nonceStr", System.currentTimeMillis() + "");
                packageParams.put("package", "prepay_id=" + prepay_id);
                packageParams.put("signType", "MD5");
                String packageSign = PaymentKit.createSign(packageParams, configShop.getAPI_KEY());
                packageParams.put("paySign", packageSign);
                String jsonStr = JsonUtils.toJson(packageParams);
                return ResponseResult.success(jsonStr);
            }else{
                packageParams.put("appId", WXPayConfig.Applet_APP_ID);
                packageParams.put("timeStamp", System.currentTimeMillis() / 1000 + "");
                packageParams.put("nonceStr", System.currentTimeMillis() + "");
                packageParams.put("package", "prepay_id=" + prepay_id);
                packageParams.put("signType", "MD5");
                String packageSign = PaymentKit.createSign(packageParams, WXPayConfig.API_KEY);
                packageParams.put("paySign", packageSign);
                String jsonStr = JsonUtils.toJson(packageParams);
                return ResponseResult.success(jsonStr);
            }
        }catch (Exception e){
            return ResponseResult.fail(e.getMessage());
        }
    }
}
